home *** CD-ROM | disk | FTP | other *** search
/ Apple II Magazines (PO) / Nibble Volume 10, No. 07 (1989-07)(MindCraft Publishing)(Side A).zip / Nibble Volume 10, No. 07 (1989-07)(MindCraft Publishing)(Side A).po / SUPERCLOCK.S < prev    next >
Text File  |  1996-12-24  |  26KB  |  643 lines

  1. ******************************************************
  2. *          SUPERCLOCK                                *
  3. *          By Peter Stubbs                           *
  4. *          Copyright(c) 1989                         *
  5. *          MindCraft Publ. Corp.                     *
  6. *          Concord, Ma 01742                         *
  7. *          MERLIN 816 ASSEMBLER                      *
  8. ******************************************************
  9.  
  10. * Will be permanently installed during ProDOS 16 boot
  11. * if placed in the SYSTEM/SYSTEM.SETUP subdirectory
  12. * of your ProDOS 16 boot disk.  This occurs because
  13. * we make the file of type $B6 (permanent initialisation
  14. * file).  Program will be made fixed and non-purgable.
  15.  
  16.  
  17.           REL            ;Tell Merlin - relocatable file
  18.           USE CLOCK.MACS ;Our macro file name
  19.           DSK CLOCK.L    ;assemble link file under this name
  20.  
  21. * Equates
  22.  
  23. BUSYFLG   EQU $E100FF    ;0 = not busy, 1 = busy
  24. INCBUSYFLG EQU $E10064
  25. DECBUSYFLG EQU $E10068
  26. OS_KIND   EQU $E100BC    ;0 = ProDOS 8, 1 = ProDOS 16
  27.  
  28.  
  29.           MX %00         ;Tel Merlin we're in 16 bits
  30.  
  31.  
  32.           PHB            ;Save data bank
  33.           PHK            ;Move program bank
  34.           PLB            ; to data bank register
  35.  
  36. * Zero our buffer and set up our flags and masks
  37.  
  38.           LDX #$00D2     ;Clear our flags etc
  39.           LDA #0000      ; to zero
  40. Loop      STA TimeBuff,X
  41.           DEX
  42.           DEX
  43.           BPL Loop       ;Until all are done
  44.  
  45. * Set up Flush Buffer vector to point at our handler
  46.  
  47.           PEA 0000       ;Space for result
  48.           PEA 0000       ;Space for result
  49.           PushWord #$0013 ;Flush Buffer
  50.           _GetVector     ;Ask for current vector
  51.           PLA            ;Get its address (low byte)
  52.           STA OldFlush+1 ; and insert into our code
  53.           PLA            ;Get address (high byte)
  54.           ShortA         ;8 bit acc. so we only store
  55.           STA OldFlush+3 ; the low byte in our code
  56.           FullA          ;Back to full 16 bits
  57.           PushWord #$0013 ;Flush Buffer
  58.           PushPtr OurFlush ;Replace current Flush Buffer vector
  59.           _SetVector     ; with a pointer to our reinstall code
  60.  
  61. * Set up BELLVECTOR to point at our handler
  62.  
  63.           PEA 0000       ;Space for result
  64.           PEA 0000       ;Space for result
  65.           PushWord #$001B ;BELLVECTOR
  66.           _GetVector     ;Ask for current vector
  67.           PLA            ;Get its address (low byte)
  68.           STA OldBell+1  ; and insert into our code
  69.           PLA            ;Get address (high byte)
  70.           ShortA         ;8 bit acc. so we only store
  71.           STA OldBell+3  ; the low byte in our code
  72.           FullA          ;Back to full 16 bits
  73.           PushWord #$001B ;BELLVECTOR
  74.           PushPtr OurBell ;Replace current BELLVECTOR with
  75.           _SetVector     ; a pointer to our reinstall code
  76.           PLB            ;Restore data bank
  77.  
  78. * This code installs the clock code into the Heartbeat Interrupt
  79. * Task queue when first run and when Option-Control-G is pressed
  80. * or when Flush Buffer (Control-Open-Apple-Delete) is pressed.
  81.  
  82. Install   PHB            ;Save data bank
  83.           PHK            ;Move program bank
  84.           PLB            ; to data bank register
  85.           LDA #$0001     ;Set tick counter to #$1
  86.           STA Timer      ; to force an update
  87.           PushPtr HrtStart
  88.           _SetHeartBeat  ;install heartbeat
  89.           ShortA         ;8 bit accumulator
  90.           LDA #%00001000
  91.           ORAL $E1C041   ;set VBL enable bit
  92.           STAL $E1C041
  93.           STZ OnFlg      ;so we know time is on (1=off)
  94.           FullA          ;16 bit accumulator
  95.           PLB            ;Restore data bank
  96.           RTL            ;Exit
  97.  
  98. * The code below is vectored to when the user issues a flush
  99. * by typing Control-Open Apple-Delete. This is one way of
  100. * reinstalling SUPERCLOCK after you have removed it, but most
  101. * ProDOS 16 applications temporarily disable this vector. To
  102. * reinstall SUPERCLOCK from such applications a second piece
  103. * of code is activated by Option-Control-G. (see below)
  104.  
  105. OurFlush  FullAXY        ;16 bit A,X,Y
  106.           JSL Install    ;Registers set up, now reinstall heartbeat
  107.           ShortAXY       ;8 bit A,X,Y
  108. OldFlush  JML $FFB5DE    ;Exit via original flush handler
  109.  
  110. * The code below is vectored to when a bell character is output.
  111. * As typing Control-G will output a bell character, this
  112. * gives us an alternative way of reinstalling SUPERCLOCK.
  113. * For cases where Control-Open Apple-Delete does not
  114. * reinstall SUPERCLOCK (e.g. the Finder) enter the control
  115. * panel by pressing Control-Open Apple-Esc and then press
  116. * Option-Control-G to reinstall SUPERCLOCK. To exit
  117. * the control panel you select QUIT and hit return.
  118.  
  119. OurBell   LDAL $E1C025   ;Get KEYMODEREG to check bit
  120.           ASL            ;Move bit 5 (pos'n of Option key) left
  121.           ASL            ; and then into carry
  122.           BCC NotOurs    ;Bit 5 = 0, so Option key not down
  123.           STAL $E1C010   ;Clear keyboard strobe to discard Ctrl-G
  124.           PHX            ;Save X
  125.           PHB            ;Save data bank
  126.           PHK            ;Move program bank
  127.           PLB            ; to data bank register
  128.           FullAXY        ;16 bit A,X,Y
  129.           JSL Install    ;Go re-install SUPERCLOCK
  130.           ShortAXY       ;8 bit A,X,Y
  131.           PLB            ;Restore bank
  132.           PLX            ;Restore X
  133.           LDY #$0        ;Y = 0 as required by Apple protocols
  134.           SEC            ;So bell is sounded
  135.           RTL
  136.  
  137. NotOurs   SEC            ;So we get a bell
  138. OldBell   JML $FFB5DE    ; exit via original interrupt handler
  139.  
  140.  
  141. HrtStart  ADRL $0000     ;Space for task pointer
  142. Timer     DA $001E       ;no. of ticks = 30 ($1E) i.e. every 1/2 sec
  143.           HEX 5AA5       ;heartbeat signature word
  144.           FullAXY        ;16 bit A,X,Y
  145.           PHB            ;Save data bank
  146.           PHK            ;Move program bank
  147.           PLB            ; to data bank register
  148.  
  149. * We will use _ReadTimeHex to get day, date and time
  150. * rather than _ReadAsciiTime to avoid problems with
  151. * some AppleWorks enhancement programs like ULTRAMACROS
  152. * that "die" when _ReadAsciiTime is used.  _Int2Dec is
  153. * then used to turn the hex values into ASCII strings.
  154.  
  155. GetTime   PEA 0000       ;Make space for result
  156.           PEA 0000
  157.           PEA 0000
  158.           PEA 0000
  159.           _ReadTimeHex   ;Get time in hex
  160.           LDA #$2020     ;Put inverse spaces between text
  161.           STA TimeBuff+19
  162.           LDA #$203A     ;": "
  163.           STA TimeBuff+16
  164.           PLA            ;Get MINUTE|SECOND
  165.           XBA            ;Swap Minutes to low byte
  166.           AND #%0000000011111111 ;remove seconds
  167.           PHA            ;Mins on stack for next tool call
  168.           PushPtr TimeBuff+17 ;Point at string output
  169.           PEA 0002       ;2 digits in string
  170.           PEA 0000       ;unsigned
  171.           _Int2Dec       ;Make MINS in hex into ASCII string
  172.           LDA TimeBuff+16 ;Get result
  173.           CMP #$203A     ;Is it : and space
  174.           BNE OK         ;No, so must be 2 digits
  175.           LDA #$303A     ;Yes, so add leading zero
  176.           STA TimeBuff+16
  177. OK        PLA            ;Get YEAR|HOUR
  178.           PHA            ;Save for later
  179.           LDX #$0D01     ;AM text
  180.           AND #%0000000011111111 ;Strip out year
  181.           BNE NOT0       ;Branch if acc <> 0
  182.           LDA #$000C     ;So 0 hours becomes 12 AM
  183.           BRA AM
  184. NOT0      CMP #$000C     ;12 or less?
  185.           BEQ PM         ;12 hours = 12 PM
  186.           BLT AM         ;1-11 hours = AM
  187.           SEC
  188.           SBC #$000C     ;Adjust to 12 hr clock
  189. PM        LDX #$0D10     ;PM text
  190. AM        STX TimeBuff+20 ;Store AM or PM text
  191.           PHA            ;HOUR on stack for next tool call
  192.           PushPtr TimeBuff+13 ;Point at string output
  193.           PEA 0003       ;3 digits (gives leading space)
  194.           PEA 0000       ;unsigned
  195.           _Int2Dec       ;Make HOUR in hex into ASCII string
  196.           PLA            ;Get YEAR|HOUR back
  197.           XBA            ;Swap high & low bytes to get HOUR|YEAR
  198.           AND #%0000000011111111 ;and mask out HOUR
  199.           PHA            ;YEAR on stack for next tool call
  200.           PushPtr TimeBuff+11 ;Point at string output
  201.           PEA 0002       ;2 digits in string
  202.           PEA 0000       ;unsigned
  203.           _Int2Dec       ;Make YEAR in hex into ASCII string
  204.           PLA            ;Get MONTH|DAY
  205.           PHA            ;Save for later
  206.           AND #%0000000011111111 ;Discard all but day
  207.           INC            ;Turn 0-30 into 1-31
  208.           PHA            ;DAY on stack for next tool call
  209.           PushPtr TimeBuff+4 ;Point at string output
  210.           PEA 0002       ;2 digits in string
  211.           PEA 0000       ;unsigned
  212.           _Int2Dec       ;Make DAY in hex into ASCII string
  213.           LDA #$202D     ;Put - and space into buffer
  214.           STA TimeBuff+6
  215.           PLA            ;Get MONTH|DAY back
  216.           XBA            ;Swap bytes so have DAY|MONTH
  217.           AND #%0000000011111111 ;Discard all but MONTH
  218.           ASL            ;Multiply
  219.           ASL            ; by 4 for table offset
  220.           TAX            ;Move to index
  221.           LDA TBL,X      ; and put the month text
  222.           STA TimeBuff+7 ; into our buffer
  223.           LDA TBL+2,X
  224.           STA TimeBuff+9
  225.           PLA            ;Get WEEKDAY|null
  226.           XBA            ;Swap bytes so have null|WEEKDAY
  227.           DEC            ;Change 1-7 to 0-6
  228.           ASL            ; and multiply
  229.           ASL            ; by 4 for table offset
  230.           TAX            ;Move to index
  231.           LDA TBL2,X     ; and put day text
  232.           STA TimeBuff   ; into our buffer
  233.           LDA TBL2+2,X
  234.           STA TimeBuff+2
  235.  
  236.           STZ Mode       ;Initialise our flags with 00
  237.           STZ EFlag
  238.           ShortA         ;8 bit accumulator
  239.           LDAL OS_KIND   ;ProDos 16 active?
  240.           BEQ Not16      ;No so use text display
  241.           LDAL $E1C029   ;Is Super Res display on ?
  242.           AND #%10000000 ;Mask out all but Super Res bit
  243.           BEQ Not16      ;No, so use text display
  244.           INC Mode       ;Mode = 1 means Super Res display
  245. Not16     FullAXY        ;16 bit A,X,Y
  246.           LDA Mode       ;Get display type
  247.           BEQ Cont       ;Prodos 8 active or Super Res off
  248.           PHA            ;Space for result
  249.           _QDStatus      ;Is QuickDraw active ?
  250.           PLA            ;Get result
  251.           BNE Cont       ;Branch if yes, all is OK for Super Res
  252.           STZ PortFlag   ;No, so clear flag
  253.           BRA ToExit     ; and exit
  254.  
  255. Cont      LDAL BUSYFLG   ;check busyflag
  256.           BEQ Cont2      ;Non zero so proceed
  257. ToExit    BRL Exit       ;else exit
  258.  
  259. Cont2     JSL INCBUSYFLG ;Set busyflag so we're not interrupted
  260.  
  261. * We have some commands that need to be checked for:-
  262. *
  263. * OPTION-D = Date display on/off (default is ON)
  264. * OPTION-W = Day of week display on/off (default is ON)
  265. * OPTION-F = Flip display position TOP/BOTTOM (default is TOP)
  266. * OPTION-I = Inverse display on/off (default is ON)
  267. * OPTION-O = Turn display on/off (default is ON)
  268. * OPTION-R = Remove program from heartbeat queue
  269. *
  270.           ShortAXY       ;8 bit A,X,Y
  271.           LDY #$0        ;Make X and Y
  272.           TYX            ; both 00
  273. Loop0     LDAL $E1C025   ;Get KEYMODEREG to check bit
  274.           ASL            ; 6 for OPTION key pressed
  275.           ASL
  276.           BCS Hit        ;Bit 6 now in carry, branch if key down
  277. ToNot     JMP Not        ; else exit keyboard test code
  278.  
  279. * Option key is down.  To let user know we're reading it we
  280. * click the speaker.  To achieve this we toggle the speaker
  281. * using a delay loop in X and Y.
  282.  
  283. Hit       INY            ;Advance first delay counter
  284.           INY            ; by two
  285.           BNE NoBeep     ;Only fall through every 128 times
  286.           INX            ;Advance second delay counter
  287.           INX            ; by two
  288.           BNE NoBeep     ;Only fall through every 128 times
  289.           STAL $E0C030   ;Now we're here, toggle speaker
  290. NoBeep    LDAL $E1C000   ;Read keyboard
  291.           BPL Loop0      ; no key is down
  292.           CMP #$E0       ;Else check for lower case
  293.           BLT NotLow
  294.           AND #$DF       ;force to upper case
  295. NotLow    CMP #"F"       ;Is it F(lip) display position
  296.           BEQ Flip       ;YES
  297.           CMP #"R"       ;Is it R(emove) heartbeat
  298.           BEQ Remove     ;YES
  299.           CMP #"I"       ;Is it I(nverse) on/off
  300.           BEQ Inverse    ;YES
  301.           CMP #"W"       ;Is it day of W(eek) on/off
  302.           BEQ Day        ;YES
  303.           CMP #"D"       ;Is it D(ate) on/off
  304.           BEQ Date       ;YES
  305.           CMP #"O"       ;Is it O(ff) / O(n)
  306.           BNE ToNot      ;NO, so exit keyboard test
  307.           LDA OnFlg      ;Get flag
  308.           EOR #$00000001 ;Reverse bit 0 (Toggles ON/OFF)
  309. GoClear   STA OnFlg      ; and update the display flag
  310.           STA EFlag      ; and the erase flag
  311.           JSR ClearIt    ;Clear current date/time
  312.           JMP CmdDone    ; and exit
  313.  
  314. ClearIt   LDA Patch1+1   ;Find current date/time location
  315.           CMP #$1D       ;will be #$1D if at top of screen
  316.           BNE Bottom
  317.           JMP ClearTop   ;Clear date/time from top and return
  318. Bottom    JMP ClearBtm   ;Clear date/time from bottom and return
  319.  
  320. Flip      JSR ClearIt    ;Clear date/time from current position
  321.           FullAXY        ;16 bit A,X,Y
  322.           LDA Patch1+1   ;Modify the date/time positioning code
  323.           EOR #$3F0      ; to flip display between top and
  324.           STA Patch1+1   ; bottom screen lines on text screen
  325.           STA Patch2+1   ; so next time we update the time it
  326.           LDA Patch3+1   ; is in the other position
  327.           EOR #$3F0
  328.           STA Patch3+1
  329.           ShortAXY       ;8 bit A,X,Y
  330.           BRA CmdDone
  331.  
  332. Remove    FullAXY        ;16 bit A,X,Y
  333.           PushPtr HrtStart
  334.           _DelHeartBeat  ;Remove from heartbeat interrupt queue
  335.           ShortAXY       ;8 bit A,X,Y
  336.           LDA #$1        ;So we set the off and erase flags
  337.           BRA GoClear    ;Now go clear date/time from screen
  338.  
  339. Inverse   LDA OrMask     ;Get current mask
  340.           EOR #%10000000 ;Reverse setting of bit 7
  341.           STA OrMask     ; and save it back
  342.           BRA CmdDone
  343.  
  344.  
  345. Day       JSR ClearIt    ;Clear current display
  346.           LDA Mode       ;Get display mode
  347.           STA EFlag      ;Makes EFlag 1 for P16 so we
  348.           LDA WFlag      ; erase the old date format
  349.           EOR #%00000001 ;Reverse the setting of the
  350.           STA WFlag      ; weekday flag and save it back
  351.           BRA CmdDone    ;All done
  352.  
  353. Date      JSR ClearIt    ;Clear current display
  354.           LDA Mode       ;Get display mode
  355.           STA EFlag      ;Makes EFlag 1 for P16 so we
  356.           LDA DFlag      ; erase the old date format
  357.           EOR #%00000001 ;Reverse the setting of the date
  358.           STA DFlag      ; flag and save it back
  359.  
  360. CmdDone   STAL $E1C010   ;Clear the keyboard strobe
  361. Not       FullAXY        ;16 bit A,X,Y
  362.           LDA Mode       ;Get current mode
  363.           BNE P16        ;Prodos 16 and Quickdraw both active
  364.           JMP P8         ;Else go to text display code
  365. P16       PHA
  366.           PHA            ;Space for result
  367.           _GetPort       ;Get pointer to current Grafport
  368.           LDA PortFlag   ;Port Initialised?
  369.           BNE InitDone
  370.  
  371. * Set up our port and restrict region
  372.  
  373.           PushPtr Port
  374.           _InitPort      ;Like OpenPort, but assumes handles OK
  375.           LDA #$0002     ;top of rectangle is screen line 2
  376.           STA PortRect
  377.           LDA #$000B     ;bottom of rectangle is screen line 11
  378.           STA PortRect+4
  379.           LDA #<ClipHndl ;Set up the clip and visible regions
  380.           STA ClipRgn    ; in our Grafport to point at ClipHndl
  381.           STA VisRgn     ; so that our handles are OK (better
  382.           LDA #^ClipHndl ; than letting QuickDraw do it as it
  383.           STA ClipRgn+2  ; takes less space and our handles
  384.           STA VisRgn+2   ; are not lost by any ClosePort commands)
  385.           INC PortFlag   ;So we know we've initialised the GrafPort
  386. InitDone  PHA            ;Space for result
  387.           _GetMasterSCB  ;Find out if we're in 640 or 320 mode
  388.           PLA            ;Get result
  389.           STA PortInfo   ;Information is also needed in GrafPort
  390.           BEQ Is320      ;00=320, 80=640
  391.           LDX #$01DA     ;Set correct dtls for 640 mode
  392.           LDY #$027C     ; left and right
  393.           BRA SetSides   ;Go set the values
  394.  
  395. Is320     LDX #$009C     ;Set correct dtls for 320 mode
  396.           LDY #$013E     ; left and right
  397. SetSides  STX PortRect+2 ;Set left pixel of our GrafPort
  398.           STX ClipRect+2 ; and our clip rectangle
  399.           STY PortRect+6 ;Set right pixel of our GrafPort
  400.           STY ClipRect+6 ; and our clip rectangle
  401.           PushPtr Port
  402.           _SetPort       ;Make our port the current one
  403.           LDA EFlag      ;Get the port erase flag
  404.           BEQ NoErase    ;00 = erase not needed
  405.           PushPtr PortRect
  406.           _EraseRect     ;Fill with bgr pattern
  407. NoErase   LDA OnFlg      ;Get display flag
  408.           BEQ Update     ;00 = show date/time
  409.           BRL NoUpdate   ; else exit update code
  410. Update    PHA            ;Space for result of next tool call
  411.           ShortA         ;8 bit accumulator
  412.           LDX #$0016     ;Clear High bit of any
  413. Loop2     LDA TimeBuff,X ; letters in the buffer
  414.           CMP #$1B       ;Is it a letter?
  415.           BGE NUM        ;Branch if not
  416.           ORA #%01000000 ;Clear, so it prints OK
  417. NUM       STA TimeBuff,X
  418.           DEX
  419.           BPL Loop2      ;Until done
  420.  
  421.           LDA DFlag      ;Get date flag (0 = show date)
  422.           BNE JustTime   ;Time only
  423.           LDA WFlag      ;Get day of week flag (0=show)
  424.           BNE NoWeek
  425.  
  426.           FullA          ;16 bit accumulator
  427.           PushPtr Length ;Point at start of string (23 chars) if
  428.           BRA DoCalc     ; date option is on
  429.  
  430.           MX %11         ;Tell Merlin we're in 8 bits
  431.  
  432. NoWeek    LDA #$12       ;No week, shorten string length to 18
  433.           STA TimeBuff+3 ; and save into buffer just before date
  434.  
  435.           MX %00         ;Tell Merlin we're in 16 bits
  436.  
  437.           FullA          ;16 bit accumulator
  438.           PushPtr TimeBuff+3 ;Now point at our shorter string
  439.           BRA DoCalc
  440.  
  441.           MX %11         ;Tell Merlin we're in 8 bits
  442.  
  443. JustTime  LDA #$08       ;Just time, shorten string length to 8
  444.           STA TimeBuff+13 ; and save into buffer just before time
  445.  
  446.           MX %00         ;Tell Merlin we're in 16 bits
  447.  
  448.           FullA          ;16 bit accumulator
  449.           PushPtr TimeBuff+13 ;Now point at our shorter time only string
  450.  
  451. DoCalc    _StringWidth   ;Get string width in pixels
  452.           PLA            ;(so we can right justify our text)
  453.           STA Width      ;and save it
  454.           LDA PortRect+6 ;Get right pixel of Port rectangle
  455.           SEC            ; then subtract the pixel width of
  456.           SBC Width      ; our string to get the left pixel
  457.           STA PortRect+2 ; and save that in Port rect definition
  458.           PHA            ;Pos'n pen horiz.
  459.           LDA #$000A     ;Get vertical pos
  460.           PHA
  461.           _MoveTo        ;Move pen to drawing location
  462.           LDA DFlag      ;Get date on flag (0 = show date)
  463.           BEQ WithDate   ;If zero, go see if we show day also
  464.           PushPtr TimeBuff+13 ;Point at time only
  465.           BRA DrawIt
  466.  
  467. WithDate  LDA WFlag      ;Get day of week flag (0 = show day)
  468.           BEQ WithWeek   ;If zero, go show it
  469.           PushPtr TimeBuff+3 ;Else point past it in buffer
  470.           BRA DrawIt     ; and go print it
  471.  
  472. WithWeek  PushPtr Length ;Point at full date/time text
  473. DrawIt    _DrawString    ;Print text in buffer to screen
  474. NoUpdate  _SetPort       ;original port ptr still on stack
  475. Exit2     JSL DECBUSYFLG ;Clear busy flag as we're all done
  476. Exit      LDA #$001E     ;Set the tick counter back to 30 (1/2 sec)
  477.           STA Timer
  478.           PLB            ;Restore data bank
  479.           ShortAXY       ;8 bit A,X,Y
  480.           RTL            ;and exit
  481.  
  482.  
  483. P8        ShortAXY       ;8 bit A,X,Y
  484.           LDA OnFlg      ;Get display flag (0 = on)
  485.           BEQ On
  486.           BRA Leave      ;Else leave display code
  487.  
  488. * Before actually displaying the time on the text screen
  489. * we need to determine whether we are in 40 or 80 column
  490. * mode.  We need to know this because we are writing
  491. * directly to the screen RAM and the way this is used is
  492. * different for the two modes.  In 40 column mode the
  493. * display RAM is from $E1400-$E17FF only, but in 80 column
  494. * mode display RAM is $E1400-$E17FF interleaved with RAM
  495. * from $E0400-$E07FF.
  496.  
  497. On        LDY #$0
  498.           TYX            ;X=0 also
  499.           LDAL $E1C01F   ;Read 40/80 column switch
  500.           BPL Forty
  501.           LDA DFlag      ;Get date flag (0 = on)
  502.           BEQ DateOn     ;Branch if date and time wanted
  503.           LDY #$E        ;Start at time text in buffer
  504.           LDX #$7        ;So we put time in correct RAM
  505.           BRA ELoop      ;ALWAYS
  506. DateOn    LDA WFlag      ;Get weekday flag (0 = on)
  507.           BEQ ELoop      ;Branch if week on
  508.           LDY #$4
  509.           LDX #$2        ;Fall through and check date flag
  510.  
  511. ELoop     LDA TimeBuff,Y ;Get character
  512.           ORA OrMask     ;Convert to current display format
  513. Patch1    STAL $E1041D,X ;Store in screen RAM
  514.           INY            ;advance buffer pointer
  515.           CPY #$16       ;Are we done ?
  516.           BEQ Leave      ;Yes, so exit
  517.           LDA TimeBuff,Y ;else get next character
  518.           ORA OrMask     ;Convert to current display format
  519. Patch2    STAL $E0041D,X ;and store in other RAM bank
  520.           INY            ;advance buffer pointer
  521.           INX            ;but not RAM pointer
  522.           CPY #$16       ;Are we done?
  523.           BEQ Leave      ;Yes, so exit
  524.           BRA ELoop      ;ALWAYS
  525. Forty     LDA DFlag      ;Get date flag (0 = on)
  526.           BEQ WeekText   ;Go see if we show weekday
  527.           LDY #$E        ;Start at time text in buffer
  528.           TYX            ;and set X to correct RAM offset
  529.           BNE FixText
  530. WeekText  LDA WFlag      ;Get weekday flag (0 = show day)
  531.           BEQ FixText
  532.           LDY #$4
  533.           TYX
  534. FixText   LDA TimeBuff,Y ;Get character
  535.           ORA OrMask     ;Convert to current display format
  536. Patch3    STAL $E00412,X ;Store in screen RAM
  537.           INY            ;Advance text pointer
  538.           INX            ;and screen RAM pointer
  539.           CPY #$16       ;Are we done?
  540.           BNE FixText    ;No, so loop back
  541. Leave     FullAXY        ;16 bit A,X,Y
  542.           JMP Exit2      ;All done, so exit
  543.  
  544.           MX %11         ;Tell Merlin we're in 8 bits
  545.  
  546. * Following code is used to erase time details from
  547. * the text screen RAM when flipped or when the display
  548. * format is otherwised changed.  The starting value
  549. * for X in the clear code depends on the display
  550. * format and so this is determined before the clear
  551. * code is executed.
  552.  
  553. ClearBtm  LDAL $E1C01F   ;Read 40/80 column switch
  554.           BPL IsForty    ;Skip 80 col stuff
  555.           LDX #$24       ;Starting position for erase
  556.           LDA DFlag      ;Get date flag (0 = on)
  557.           BNE ClrBtm2    ;Branch if date off
  558.           LDX #$1F       ;Change starting pos'n
  559.           LDA WFlag      ;Get weekday flag (0 = on)
  560.           BNE ClrBtm2    ;Branch if weekday off
  561.           LDX #$1D       ;Change starting pos'n
  562.           BRA ClrBtm2    ;Go to start of clear code
  563. IsForty   LDX #$20       ;Starting position for erase
  564.           LDA DFlag      ;Get date flag (0 = on)
  565.           BNE ClrBtm2    ;Branch if date off
  566.           LDX #$16       ;Starting position for erase
  567.           LDA WFlag      ;Get Weekday flag (0 = on)
  568.           BNE ClrBtm2    ;Branch if weekday off
  569.           LDX #$12       ;If weekday on
  570. ClrBtm2   LDA #$A0       ;Load acc. with a space
  571. BLoop     STAL $E107D0,X ;and modify screen RAM
  572.           STAL $E007D0,X
  573.           INX            ;advance screen RAM pointer
  574.           CPX #$28       ;Are we done?
  575.           BNE BLoop      ;No, so loop
  576.           RTS            ;Else return to caller
  577.  
  578. * Similar code to the ClearBtm routine
  579.  
  580. ClearTop  LDAL $E1C01F
  581.           BPL IsForty2
  582.           LDX #$24
  583.           LDA DFlag
  584.           BNE ClrTop2
  585.           LDX #$1F
  586.           LDA WFlag
  587.           BNE ClrTop2
  588.           LDX #$1D
  589.           BRA ClrTop2
  590. IsForty2  LDX #$20
  591.           LDA DFlag
  592.           BNE ClrTop2
  593.           LDX #$16
  594.           LDA WFlag
  595.           BNE ClrTop2
  596.           LDX #$12
  597. ClrTop2   LDA #$A0
  598. TLoop     STAL $E10400,X
  599.           STAL $E00400,X
  600.           INX
  601.           CPX #$28
  602.           BNE TLoop
  603.           RTS
  604.  
  605. TBL       INV "JAN-FEB-MAR-APR-MAY-JUN-JUL-AUG-SEP-OCT-NOV-DEC-"
  606. TBL2      INV "SUN MON TUE WED THU FRI SAT "
  607.  
  608.           MX %00         ;Tell Merlin we're in 16 bits
  609.  
  610. Clip      DA 10          ;This is part of the region definition
  611. ClipRect  DA 1,477,11,636 ;Top,Left,Bottom,Right of our rect
  612.  
  613. ClipHndl  ADRL Clip      ;Handle to the clip and visible regions
  614.  
  615. Length    DB 23          ;Length of string that will hold date/time
  616.  
  617.           ASC ' '        ;Include a leading space before date/time
  618. TimeBuff  EQU *          ;Holds the date/time string
  619. PortFlag  EQU TimeBuff+22 ;0=Init done, 1=Not done
  620. OnFlg     EQU PortFlag+2 ;0=ON, 1=OFF
  621. Mode      EQU OnFlg+2    ;0=P8, 1=P16
  622. EFlag     EQU Mode+2     ;Non zero = erase needed
  623. DFlag     EQU EFlag+2    ;0=Date, 1=No Date
  624. WFlag     EQU DFlag+2    ;0=Day of week, 1=No Day of week
  625. OrMask    EQU WFlag+2    ;Used to force inverse/normal text
  626. Width     EQU OrMask+1   ;Holds date/time width in pixels
  627.  
  628. * grafPort record
  629.  
  630. Port      EQU Width+2
  631. PortInfo  EQU Port       ;portSCB
  632. PortRect  EQU Port+16
  633. ClipRgn   EQU Port+24
  634. VisRgn    EQU Port+28
  635.  
  636. * In order to make the program occupy less disk space
  637. * all buffers are here at the end and only equates are
  638. * included in the source file.  When the program is
  639. * run, the OMF loader will allocate the buffer
  640. * as requested by the link file that is used to assemble
  641. * this file.  If using another assembler you may need
  642. * to use DS $D2 here instead.
  643.